﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace AtlantisRevenge.GamePlay
{
    public enum ObjectStatus
    {
        Active,
        Dying,
        Dead
    }

    public class GameplayObject
    {
        #region Status Data

        ObjectStatus status;
        public ObjectStatus Status
        {
            get { return status; }
        }

        Boolean visible = true;
        public Boolean Visible
        {
            get { return visible; }
            set { visible = value; }
        }

        #endregion

        #region Graphics Data

        Boolean lookRight = true;
        public Boolean LookRight
        {
            get { return lookRight; }
            set { lookRight = value; }
        }

        Texture2D texture;
        public Texture2D Texture
        {
            get { return texture; }
            set { texture = value; }
        }

        Rectangle originRectangle;
        public Rectangle OriginRectangle
        {
            get { return originRectangle; }
            set { originRectangle = value; }
        }

        Rectangle destinyRectangle;
        public Rectangle DestinyRectangle
        {
            get { return destinyRectangle; }
            set { destinyRectangle = value; }
        }

        public Vector2 Origin
        {
            get
            { return new Vector2(0, 0); }
        }

        float opacity = 1.0f;
        byte Alpha
        {
            get { return (byte)(opacity * 255); }
        }

        Color color = Color.White;
        protected Color Color
        {
            get { return new Color(color.R, color.G, color.B, Alpha); }
            set { color = value; }
        }

        Boolean animated = false;
        public Boolean Animated
        {
            get { return animated; }
            set { animated = value; }
        }

        public struct animation
        {
            int frame_X;
            public int Frame_X
            {
                get { return frame_X; }
                set { frame_X = value; }
            }

            public int Frame_Y
            {
                get { return frame_X; }
                set { frame_X = value; }
            }

            public int NumberFrames
            {
                get { return frame_X; }
                set { frame_X = value; }
            }

            public int FPS
            {
                get { return frame_X; }
                set { frame_X = value; }
            }

            public int Y
            {
                get { return frame_X; }
                set { frame_X = value; }
            }

            public int CurrentFrame
            {
                get { return frame_X; }
                set { frame_X = value; }
            }
        }

        animation currentAnimation;
        public animation CurrentAnimation
        {
            get { return currentAnimation; }
            set { currentAnimation = value; }
        }

        float layer = 1.0f;
        public float Layer
        {
            get { return layer; }
            set { layer = value; }
        }

        #endregion

        #region Physics Data

        Rectangle colisionRect;
        public Rectangle ColisionRect
        {
            get
            { return colisionRect; }
            set
            { colisionRect = value; }

        }

        Vector2 position = Vector2.Zero;
        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }

        Vector2 speed = Vector2.Zero;
        public Vector2 Velocity
        {
            get { return speed; }
            set { speed = value; }
        }

        float rotation = 0f;
        public float Rotation
        {
            get { return rotation; }
            set { rotation = value; }
        }

        float scale = 1.0f;
        public float Scale
        {
            get { return scale; }
            set { scale = value; }
        }

        GameWindow window;
        public GameWindow Window
        {
            get { return window; }
            set { window = value; }
        }

        bool mouseOverSprite;
        public bool MouseOverSprite
        {
            get { return mouseOverSprite; }
        }

        #endregion

        #region Die Data

        /// <summary>
        /// The time it takes for our object to die
        /// </summary>
        TimeSpan dieTime = TimeSpan.Zero;
        public TimeSpan DieTime
        {
            get { return dieTime; }
            set { dieTime = value; }
        }

        /// <summary>
        /// 0.0 - fully alive and 100% opacity, 1.0 - fully dead and 0% opacity.
        /// </summary>
        float diePercent = 0.0f;

        #endregion

        #region Initialization Methods
        public virtual void Initialize()
        {
            if (!(status == ObjectStatus.Active))
                status = ObjectStatus.Active;

            colisionRect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
        }// GameObject Initialize Control
        #endregion

        public virtual void Update(GameTime gameTime)
        {
            if (status == ObjectStatus.Active)
            {
                position += Vector2.Multiply(speed, (float)gameTime.ElapsedGameTime.TotalSeconds);
                if (texture != null)
                    originRectangle = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
            }
            else if (status == ObjectStatus.Dying)
            {
                Dying(gameTime);
            }

            mouseOverSprite = MouseOverSpriteCheck();

            if (this is Fleet)
            {
                //Console.WriteLine(mouseOverSprite.ToString() + " " + new Vector2(Main.CurrentMouseState.X, Main.CurrentMouseState.Y).ToString() + " " + new Vector2(position.X, position.Y).ToString());
            }
        }// Update's the game every frame

        private void Dying(GameTime gameTime)
        {
            if (diePercent >= 1)
                status = ObjectStatus.Dead;
            else
            {
                float dieDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / dieTime.TotalMilliseconds);
                diePercent += dieDelta;
                opacity -= dieDelta;

                if (opacity < 0)
                    opacity = 0;
            }
        }// Control's from Dying to Dead status

        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            if (visible)
            {
                if ((texture != null) && (spriteBatch != null))
                {
                    if (animated)
                    {
                        int frame = (int)(gameTime.TotalGameTime.TotalSeconds * currentAnimation.FPS) % currentAnimation.NumberFrames;

                        spriteBatch.Draw(texture, new Rectangle((int)position.X, (int)position.Y, currentAnimation.Frame_X, currentAnimation.Frame_Y),
                            new Rectangle(frame * currentAnimation.Frame_X, currentAnimation.Frame_Y, currentAnimation.Frame_X, currentAnimation.Frame_Y),
                            color, rotation, Origin, (lookRight) ? SpriteEffects.None : SpriteEffects.FlipHorizontally, layer);
                    }
                    else
                    {
                        spriteBatch.Draw(texture, position, null, Color, rotation, Origin, scale, (lookRight) ? SpriteEffects.None : SpriteEffects.FlipHorizontally, layer);
                    }
                }
            }
        }// GameObject Draw Control

        public virtual void CollisionTRGT(GameplayObject target) { }

        public void Die()
        {
            if (status == ObjectStatus.Active)
            {
                if (dieTime != TimeSpan.Zero)
                    status = ObjectStatus.Dying;
                else
                    status = ObjectStatus.Dead;
            }
        }// Initializes Dying status

        public void NormalizeVelocity()
        {
            speed.Normalize();
        }// normalize velocity after rotation

        public float FromPixelPerLoop(float pixels)
        {
            return pixels / (1f / 60f);
        }// Speed variable calculator

        Boolean MouseOverSpriteCheck()
        {
            if ((Main.CurrentMouseState.X > Position.X && Main.CurrentMouseState.X <= Position.X + Texture.Width) && (Main.CurrentMouseState.Y > Position.Y && Main.CurrentMouseState.Y <= Position.Y + Texture.Height))
            {
                return true;
            }
            else
            {
                return false;
            }
        }// Check if mouse is over the sprite
    }
}